package org.fizz.handlerequest;

import java.net.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.stream.Stream;

import static org.fizz.handlerequest.ConfigKeyConstant.*;

/**
 * @Author Fizz Pu
 * @Date 2021/5/6 下午11:59
 * @Version 1.0
 * 失之毫厘，缪之千里！
 */

public class AbstractLocalConfig implements LocalConfig {

    private static int id = 1;

    public AbstractLocalConfig() throws SocketException {
        refresh();
    }

    /**
     * {"wireless": {
     *     ""
     *     "ipV4": "122312",
     *     "ipV6":"123",
     *     "macString":"121231",
     *
     * }, os:"linux", cpuAch: "" }
     */
    protected Map<String, Object> configPools = new ConcurrentHashMap<>();

    // 加载配置信息 当断网或者联网时事件发生时要重新加载网卡
    protected void refresh() throws SocketException {
        configPools.put(cpuArch,System.getProperty("os.arch"));
        configPools.put(osType, System.getProperty("os.name"));

        // 获得搜有可用的物理网卡接口, 虚拟网卡除外
        Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();

        while (networkInterfaces.hasMoreElements()) {
                NetworkInterface networkInterface = networkInterfaces.nextElement(); // 网卡
                Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses(); // 地址

                Map<String, String> ipMacInfo = new HashMap<>();

                configPools.put(netInterfaceName + id, ipMacInfo);
                id ++;

                while (inetAddresses.hasMoreElements()) {

                    InetAddress inetAddress = inetAddresses.nextElement();
                    String name = networkInterface.getDisplayName(); // 网卡名字
                    if (name.contains("Adapter") || name.contains("Virtual")
                            || name.contains("VMnet") || name.contains("#")) {
                        continue;
                    }
                    if (networkInterface.isVirtual() || !networkInterface.isUp() || !networkInterface.supportsMulticast()) {
                        continue;
                    }

                    if(inetAddress == null){
                        continue;
                    }

                    String sMAC;
                    StringBuilder stringBuilder = new StringBuilder();
                    byte[] macBuf = networkInterface.getHardwareAddress();
                    for (byte ele : macBuf) {
                        stringBuilder.append(Integer.toHexString(Byte.toUnsignedInt(ele)));
                    }
                    sMAC = stringBuilder.toString();

                    ipMacInfo.put(macName, sMAC);
                    ipMacInfo.put(netInterfaceName, networkInterface.getDisplayName());

                    String ip;
                    ip = inetAddress.getHostName();
                    if (inetAddress instanceof Inet4Address) {
                        ipMacInfo.put(ipV4Name, ip);
                    } else {
                        ipMacInfo.put(ipV6Name, ip);
                    }
                }
            }
    }

    public class ConfigInterfaceIterator implements Iterator<Map<String, String>> {

        Iterator<Map.Entry<String, Object>> iterator = configPools.entrySet().iterator();

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

        @Override
        public void forEachRemaining(Consumer<? super Map<String , String>> action) {
            throw new UnsupportedOperationException();
        }

        @Override
        public boolean hasNext() {
            return iterator.hasNext();
        }

        @Override
        public Map<String, String> next() {
            while (iterator.hasNext()) {
                Map.Entry<String, Object> entry = iterator.next();
                String key = entry.getKey();

                if (key.startsWith(netInterfaceName)) {
                    return (Map<String, String>) entry.getValue();
                }
            }

            throw new IndexOutOfBoundsException("超过范围");
        }
    }

    @Override
    public void forEach(Consumer<? super Map<String, String>> action) {
        for (Map<String, String> stringStringMap : this) {
            action.accept(stringStringMap);
        }
    }

    @Override
    public Iterator<Map<String, String>> iterator() {
        return new ConfigInterfaceIterator();
    }

    @Override
    public Spliterator spliterator() {
        throw new UnsupportedOperationException();
    }
}
